package com.hcy.app.screen.cipher

import org.bouncycastle.crypto.engines.SM4Engine
import org.bouncycastle.crypto.modes.CBCBlockCipher
import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher
import org.bouncycastle.crypto.params.KeyParameter
import org.bouncycastle.crypto.params.ParametersWithIV
import org.bouncycastle.util.encoders.Hex
import java.security.SecureRandom

object CryptUtilsForSm4 {
    private const val BLOCK_SIZE = 16 // SM4分组长度为16字节


    /**
     * 生成随机SM4密钥
     * @return 随机密钥字符串
     */
    fun generateKeyString(): String {
        val key = ByteArray(BLOCK_SIZE)
        SecureRandom().nextBytes(key)
        return Hex.toHexString(key) // 使用Hex编码
    }
    /**
     * 生成随机初始化向量(IV)
     * @return 16字节的随机IV
     */
    fun generateIVString(): String {
        val iv = ByteArray(BLOCK_SIZE)
        SecureRandom().nextBytes(iv)
        return Hex.toHexString(iv) // 使用Hex编码
    }

    fun generate(): Pair<String, String>{
        return Pair(generateKeyString(),generateIVString())
    }

    /**
     * SM4加密（CBC模式）
     * @param plaintext 明文
     * @param keyHex 密钥（16字节）
     * @param ivHex 初始化向量（16字节）
     * @return 十六进制字符串表示的密文
     */
    fun encryptCBC(plaintext: String, keyHex: String, ivHex: String): String {
        val plaintextBytes = plaintext.toByteArray(Charsets.UTF_8)
        val keyBytes = Hex.decode(keyHex) // 解码Hex字符串得到原始字节
        val ivBytes = Hex.decode(ivHex) // 解码Hex字符串得到原始字节

        val cipher = PaddedBufferedBlockCipher(CBCBlockCipher(SM4Engine()))
        cipher.init(true, ParametersWithIV(KeyParameter(keyBytes), ivBytes))

        val output = ByteArray(cipher.getOutputSize(plaintextBytes.size))
        var len = cipher.processBytes(plaintextBytes, 0, plaintextBytes.size, output, 0)
        len += cipher.doFinal(output, len)
        val ciphertext = output.copyOf(len)
        return Hex.toHexString(ciphertext)
    }


    /**
     * SM4解密（CBC模式）
     * @param ciphertextHex 十六进制字符串表示的密文
     * @param keyHex 密钥（16字节）
     * @param ivHex 初始化向量（16字节）
     * @return 解密后的明文
     */
    fun decryptCBC(ciphertextHex: String, keyHex: String, ivHex: String): String {
        val ciphertext = Hex.decode(ciphertextHex)
        val keyBytes = Hex.decode(keyHex) // 解码Hex字符串得到原始字节
        val ivBytes = Hex.decode(ivHex)   // 解码Hex字符串得到原始字节

        val cipher = PaddedBufferedBlockCipher(CBCBlockCipher(SM4Engine()))
        cipher.init(false, ParametersWithIV(KeyParameter(keyBytes), ivBytes))

        val output = ByteArray(cipher.getOutputSize(ciphertext.size))
        var len = cipher.processBytes(ciphertext, 0, ciphertext.size, output, 0)
        len += cipher.doFinal(output, len)
        val decrypted = output.copyOf(len)

        return String(decrypted, Charsets.UTF_8)
    }

    /**
     * SM4加密（ECB模式）
     */
    fun encryptECB(plaintext: String, keyHex: String): String {
        val plaintextBytes = plaintext.toByteArray(Charsets.UTF_8)
        val keyBytes = Hex.decode(keyHex) // 解码Hex字符串得到原始字节

        val cipher = PaddedBufferedBlockCipher(SM4Engine())
        cipher.init(true, KeyParameter(keyBytes))

        val output = ByteArray(cipher.getOutputSize(plaintextBytes.size))
        var len = cipher.processBytes(plaintextBytes, 0, plaintextBytes.size, output, 0)
        len += cipher.doFinal(output, len)

        val ciphertext = output.copyOf(len)
        return Hex.toHexString(ciphertext)
    }

    /**
     * SM4解密（ECB模式）
     */
    fun decryptECB(ciphertextHex: String, keyHex: String): String {
        val ciphertext = Hex.decode(ciphertextHex)
        val keyBytes = Hex.decode(keyHex) // 解码Hex字符串得到原始字节

        val cipher = PaddedBufferedBlockCipher(SM4Engine())
        cipher.init(false, KeyParameter(keyBytes))

        val output = ByteArray(cipher.getOutputSize(ciphertext.size))
        var len = cipher.processBytes(ciphertext, 0, ciphertext.size, output, 0)
        len += cipher.doFinal(output, len)

        val decrypted = output.copyOf(len)
        return String(decrypted, Charsets.UTF_8)
    }

}